Skip to content

fix(spec): reconcile the api and platform skill indexes with what their bodies teach - #15424

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-15361-skill-map-api-platform-pointers
Sep 5, 2026
Merged

fix(spec): reconcile the api and platform skill indexes with what their bodies teach#15424
os-zhuang merged 4 commits into
mainfrom
claude/issue-15361-skill-map-api-platform-pointers

Conversation

@claude

@claude claude Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #15361
Fixes #15264

Executes maintainer decision batch #36 (1 A · 2 A) and, on the patch round,
maintainer decision batch #39 (ruling D). One rule throughout — the index
advertises what the SKILL.md teaches
— applied in three directions: drop a
pointer the body never teaches, add a pointer the body teaches, and constrain
the transitive closure to the members the body names.

What changed

direction package pointer rule applied
dropped objectstack-api api/rest-server.zod.ts Advertised, never taught. The skill's authored markdown names the file nowhere — not RestServerConfig, not one of its sub-configs, not the words "rest server" — while every other core entry is reachable from the body by at least one exported name. An index entry is a POINTER; pointing at a schema the body cannot help with sends an agent into node_modules for a lesson that does not exist. The schema keeps existing and stays importable.
added objectstack-platform stack.zod.ts (root-level in packages/spec/src) Taught, never advertised. The body's main subject is defineStack(), and it names ObjectStackDefinitionSchema, ObjectStackDefinition, ObjectStackDefinitionInput and ObjectStack in its own prose, while the catalogue had no pointer to the file declaring them.
constrained objectstack-platform TRANSITIVE_ALLOWLIST (5 of 73 closure members) Ruling D. objectstack-platform declared no allowlist, so it published its whole import closure; the added core pointer took that closure to 73 transitive rows, most of them shapes the body never teaches. The allowlist is populated by one mechanical rule and nothing else — see the census below.

The map spells the added entry 'stack.zod.ts' with no directory segment: the generator resolves every core entry with path.resolve(SPEC_SRC, rel) against packages/spec/src, so a root-level file is spelled bare, as kernel/... ones carry their directory.

The item-2 fork — resolved by ruling D

The fork this PR raised for the approvers (one core pointer publishing 46 further
transitive ones) was ruled in decision batch #39: declare
TRANSITIVE_ALLOWLIST['objectstack-platform'], populated by a mechanical census
and nothing else, then regenerate. That is what this round does.

The rule, and nothing else. A member of objectstack-platform's import
closure stays only if skills/objectstack-platform/SKILL.md names at least
one of that module's exported names, as an exact word-bounded identifier
(backticked or bare). No judgement rows, no hand-picked keeps or drops.

Where the entry lives. The ruling names
packages/spec/scripts/build-skill-references.ts. TRANSITIVE_ALLOWLIST is not
declared there — it is declared in packages/spec/scripts/lib/skill-map-guards.ts
and imported by the generator, next to checkTransitiveAllowlist, the guard that
constrains it. The entry was therefore added at that declaration; the ruling's
substance is unchanged and no second surface was created. This is the one
mechanism assumption in the ruling that did not hold, and it is reported rather
than worked around.

How the census was taken, reproducibly.

  • The closure is the generator's own — read from the emitted
    skills/objectstack-platform/references/_index.md at the pre-allowlist head,
    not re-derived by hand: 10 core entries + 73 transitive members.
  • Exported names come from each module itself — export const|let|var,
    export function|class|type|interface|enum|namespace, and the names in
    export { … } / export type { … } clauses, alias targets included. 1,244
    exported names were read across the 73 modules. No module in the closure uses
    export *, so nothing is reachable that this extraction cannot see.
    The extraction was cross-checked against the repo's own TypeScript-derived
    packages/spec/export-origins/*.json (which records the declaring file of every
    name each public entry point exports): for all 73 modules, every name that
    artifact attributes to the module is in the extracted set — 0 missing.
  • The grep runs over skills/objectstack-platform/SKILL.md only
    never over references/**, which this generator writes.

Result: 5 of 73 kept. Both shapes the fork named fall out by the rule, not by
hand: automation/state-machine.zod.ts (retired by ADR-0020 as a record-lifecycle
declaration) and data/date-macros.zod.ts (moved to one owning package) are gone
from the index, and neither was touched by hand.

The census

Every closure member, its exported names, the name the SKILL.md carries, and the
verdict. The census read all 1,244 names; the middle column shows the first
six per module so the table stays readable — the cap is a display cap, not a
census cap.

closure member exported names (all read; list shown to 6) name the SKILL.md carries verdict
ai/agent.zod.ts AIModelConfigSchema, Agent, AgentParsed, AgentSchema, StructuredOutputConfig, StructuredOutputConfigParsed … +6 more (12 total) none dropped
ai/skill.zod.ts SKILL_TRIGGER_LIST_VALUE_OPERATORS, SKILL_TRIGGER_SCALAR_VALUE_OPERATORS, Skill, SkillParsed, SkillSchema, SkillTriggerCondition … +2 more (8 total) none dropped
ai/tool.zod.ts Tool, ToolSchema, defineTool (3 total) none dropped
api/endpoint.zod.ts ApiEndpoint, ApiEndpointParsed, ApiEndpointSchema, ApiMapping, ApiMappingSchema, normalizeEndpointPath (6 total) none dropped
api/errors.zod.ts EnhancedApiError, EnhancedApiErrorParsed, EnhancedApiErrorSchema, ErrorCategory, ErrorHttpStatusMap, ErrorResponse … +9 more (15 total) none dropped
automation/control-flow.zod.ts FlowGraph, FlowRegion, FlowRegionParsed, FlowRegionSchema, LOOP_MAX_ITERATIONS_CEILING, LOOP_NODE_TYPE … +26 more (32 total) none dropped
automation/flow-function.zod.ts DEFAULT_FLOW_FUNCTION_EFFECT, FlowFunctionCallable, FlowFunctionDeclaration, FlowFunctionDeclarationParsed, FlowFunctionDeclarationSchema, FlowFunctionEffect … +7 more (13 total) none dropped
automation/flow.zod.ts FLOW_BUILTIN_NODE_TYPES, FLOW_STRUCTURAL_NODE_TYPES, Flow, FlowEdge, FlowEdgeParsed, FlowEdgeSchema … +11 more (17 total) none dropped
automation/state-machine.zod.ts ActionRef, ActionRefSchema, GuardRef, GuardRefSchema, StateMachineConfig, StateMachineSchema … +5 more (11 total) none dropped
automation/webhook.zod.ts Webhook, WebhookParsed, WebhookSchema, WebhookTriggerType, defineWebhook (5 total) none dropped
data/analytics.zod.ts AggregationMetricType, AnalyticsQuery, AnalyticsQuerySchema, Cube, CubeJoin, CubeJoinParsed … +10 more (16 total) none dropped
data/date-macros.zod.ts DATE_MACRO_ALIAS_TOKENS, DATE_MACRO_DESCRIPTIONS, DATE_MACRO_INSTANT_TOKENS, DATE_MACRO_PARAM_RE, DATE_MACRO_PERIOD_TOKENS, DATE_MACRO_TOKENS … +11 more (17 total) none dropped
data/driver-sql.zod.ts DataTypeMapping, DataTypeMappingSchema, SQLDialect, SQLDialectSchema, SQLDriverConfig, SQLDriverConfigParsed … +6 more (12 total) none dropped
data/driver.zod.ts DriverCapabilities, DriverCapabilitiesSchema, DriverConfig, DriverConfigParsed, DriverConfigSchema, DriverInterface … +7 more (13 total) none dropped
data/driver/common.zod.ts CANONICAL_CREDENTIAL_KEYS, CREDENTIAL_KEY_SPELLINGS, CREDENTIAL_URL_QUERY_PARAMS, CREDENTIAL_URL_QUERY_PARAM_NAMES, DriverSslToggle, DriverSslToggleSchema … +24 more (30 total) none dropped
data/driver/config-registry.zod.ts BUILTIN_DRIVER_IDS, BuiltinDriverId, DATABASE_DRIVER_SELECTION_ALIASES, DATABASE_DRIVER_SELECTION_IDS, DRIVER_CONFIG_SCHEMAS, DRIVER_ID_ALIASES … +8 more (14 total) none dropped
data/driver/memory.zod.ts AutoPersistenceConfig, AutoPersistenceConfigSchema, CustomPersistenceConfig, CustomPersistenceConfigSchema, FilePersistenceConfig, FilePersistenceConfigParsed … +15 more (21 total) none dropped
data/driver/mongo.zod.ts MongoConfig, MongoConfigParsed, MongoConfigSchema, MongoDriverSpec, getMongoConfigJsonSchema (5 total) none dropped
data/driver/mysql.zod.ts MysqlConfig, MysqlConfigParsed, MysqlConfigSchema, getMysqlConfigJsonSchema (4 total) none dropped
data/driver/postgres.zod.ts PostgresConfig, PostgresConfigParsed, PostgresConfigSchema, getPostgresConfigJsonSchema (4 total) none dropped
data/driver/sqlite.zod.ts SqliteConfig, SqliteConfigParsed, SqliteConfigSchema, SqliteWasmConfig, SqliteWasmConfigParsed, SqliteWasmConfigSchema … +4 more (10 total) none dropped
data/driver/turso.zod.ts TursoConfig, TursoConfigParsed, TursoConfigSchema, TursoDriverSpec, TursoTransportMode, TursoTransportModeSchema … +1 more (7 total) none dropped
data/field-value.zod.ts AddressSchema, AddressValue, AddressValueSchema, BOOLEAN_VALUE_TYPES, CALENDAR_DATE_TYPES, CLOCK_TIME_TYPES … +33 more (39 total) none dropped
data/field.zod.ts Address, AddressSchema, BOUNDED_STRING_FIELD_TYPES, CurrencyConfig, CurrencyConfigParsed, CurrencyConfigSchema … +28 more (34 total) Field, FieldSchema kept
data/filter.zod.ts ALL_OPERATORS, ComparisonOperatorSchema, EqualityOperatorSchema, FILTER_ARRAY_LOGIC_KEYWORDS, FILTER_OPERATORS, FieldOperators … +39 more (45 total) none dropped
data/hook-body.zod.ts ExpressionBody, ExpressionBodySchema, HookBody, HookBodyCapability, HookBodyParsed, HookBodySchema … +3 more (9 total) none dropped
data/hook.zod.ts Hook, HookContext, HookContextSchema, HookDispatch, HookEvent, HookEventType … +4 more (10 total) Hook kept
data/mapping.zod.ts ImportFieldMapping, ImportFieldMappingParsed, ImportFieldMappingSchema, Mapping, MappingParsed, MappingSchema … +2 more (8 total) none dropped
data/object.zod.ts API_OPERATION_ORDER, ApiMethod, ApiOperation, ApiOperationSchema, CrudAffordances, IndexSchema … +43 more (49 total) Lifecycle, ObjectSchema kept
data/query.zod.ts AggregationFunction, AggregationNode, AggregationNodeSchema, DateGranularity, DateGranularityValue, FieldNode … +14 more (20 total) none dropped
data/validation.zod.ts BaseValidationRuleShape, ConditionalValidation, ConditionalValidationParsed, ConditionalValidationSchema, CrossFieldValidation, CrossFieldValidationParsed … +15 more (21 total) none dropped
identity/position.zod.ts AUDIENCE_ANCHOR_POSITIONS, EVERYONE_POSITION, GUEST_POSITION, Position, PositionParsed, PositionSchema … +1 more (7 total) none dropped
integration/connector.zod.ts CircuitBreakerConfig, CircuitBreakerConfigParsed, CircuitBreakerConfigSchema, Connector, ConnectorAction, ConnectorActionEffect … +52 more (58 total) none dropped
kernel/cluster.zod.ts ClusterCapabilityConfig, ClusterCapabilityConfigParsed, ClusterCapabilityConfigSchema, ClusterDriver, ClusterDriverSchema, ClusterTenantIsolation … +15 more (21 total) none dropped
kernel/metadata-loader.zod.ts MetadataFallbackStrategy, MetadataFallbackStrategySchema, MetadataManagerConfig, MetadataManagerConfigParsed, MetadataManagerConfigSchema (5 total) none dropped
kernel/metadata-protection.zod.ts MetadataLock, MetadataLockSchema, MetadataLockSource, MetadataLockSourceSchema, MetadataProtectionFields, MetadataProvenance … +5 more (11 total) none dropped
security/permission.zod.ts AdminScope, AdminScopeParsed, AdminScopeSchema, EffectiveObjectPermission, EffectiveObjectPermissionSchema, FieldPermission … +11 more (17 total) none dropped
security/rls.zod.ts RLS, RLSEvaluationResult, RLSEvaluationResultSchema, RLSOperation, RLSUserContext, RLSUserContextSchema … +3 more (9 total) RLS kept
security/sharing.zod.ts CriteriaSharingRule, CriteriaSharingRuleParsed, CriteriaSharingRuleSchema, OWDModel, ShareRecipientType, SharingLevel … +5 more (11 total) none dropped
shared/connector-auth.zod.ts ConnectorAPIKeySchema, ConnectorAuthConfig, ConnectorAuthConfigParsed, ConnectorAuthConfigSchema, ConnectorBasicAuthSchema, ConnectorBearerAuthSchema … +13 more (19 total) none dropped
shared/enums.zod.ts IsolationLevel, IsolationLevelEnum, MutationEvent, MutationEventEnum, SortDirection, SortDirectionEnum … +2 more (8 total) none dropped
shared/error-map.zod.ts ObjectStackRawIssue, formatZodError, formatZodIssue, objectStackErrorMap, safeParsePretty (5 total) none dropped
shared/expression.zod.ts CronExpressionInput, CronExpressionInputSchema, Expression, ExpressionDialect, ExpressionInput, ExpressionInputSchema … +15 more (21 total) none dropped
shared/http.zod.ts CorsConfig, CorsConfigParsed, CorsConfigSchema, HttpMethod, HttpMethodSubset, HttpMethodSubsetSchema … +8 more (14 total) none dropped
shared/identifiers.zod.ts METADATA_ITEM_NAME_PATTERN, MetadataItemName, MetadataItemNameSchema, QUALIFIED_ITEM_NAME_PATTERN, SnakeCaseIdentifier, SnakeCaseIdentifierSchema … +2 more (8 total) none dropped
shared/mapping.zod.ts FieldMapping, FieldMappingSchema (2 total) none dropped
shared/metadata-collection.zod.ts MAP_SUPPORTED_FIELDS, METADATA_ALIASES, MapSupportedField, MetadataCollectionInput, NormalizeStackInputOptions, PLURAL_TO_SINGULAR … +6 more (12 total) none dropped
shared/metadata-types.zod.ts BaseMetadataRecord, BaseMetadataRecordSchema, MetadataFormat, MetadataFormatSchema (4 total) none dropped
shared/protection.zod.ts ApplyProtectionContext, Protection, ProtectionSchema, applyProtection (4 total) none dropped
shared/retry-policy.zod.ts RetryPolicy, RetryPolicyParsed, RetryPolicySchema, retryPolicyShape (4 total) none dropped
shared/suggestions.zod.ts KeySetGuidance, StrictUnknownKeyErrorOptions, findClosestMatches, formatSuggestion, keySetMatches, levenshteinDistance … +2 more (8 total) none dropped
shared/value-domain.zod.ts ISO_3166_ALPHA2_CODES, ValueDomain, ValueDomainSchema, isValueDomainMember (4 total) none dropped
system/book.zod.ts AudienceBook, AudienceCaller, Book, BookAudience, BookAudienceSchema, BookGroup … +21 more (27 total) none dropped
system/deploy-bundle.zod.ts DeployBundle, DeployBundleParsed, DeployBundleSchema, DeployDiff, DeployDiffParsed, DeployDiffSchema … +18 more (24 total) none dropped
system/doc.zod.ts Doc, DocSchema, DocTranslation, resolveDocLocale (4 total) none dropped
system/email-template.zod.ts EmailTemplateDefinition, EmailTemplateDefinitionCategory, EmailTemplateDefinitionCategorySchema, EmailTemplateDefinitionParsed, EmailTemplateDefinitionSchema, EmailTemplateDefinitionVariable … +3 more (9 total) none dropped
system/job.zod.ts CronSchedule, CronScheduleParsed, CronScheduleSchema, IntervalSchedule, IntervalScheduleSchema, Job … +14 more (20 total) none dropped
system/stack-server.zod.ts ServerRateLimitConfig, ServerRateLimitConfigParsed, ServerRateLimitConfigSchema, StackServerConfig, StackServerConfigParsed, StackServerConfigSchema … +3 more (9 total) none dropped
system/tenant.zod.ts DatabaseLevelIsolationStrategy, DatabaseLevelIsolationStrategyParsed, DatabaseLevelIsolationStrategySchema, DatabaseProvider, DatabaseProviderSchema, QuotaEnforcementResult … +23 more (29 total) none dropped
system/translation.zod.ts ActionResultDialogTranslation, ActionResultDialogTranslationSchema, CoverageBreakdownEntry, CoverageBreakdownEntrySchema, FieldTranslation, FieldTranslationSchema … +22 more (28 total) none dropped
ui/action-params.zod.ts ACTION_PARAM_BUILTIN_KEYS, ActionEngineFacade, ActionHandler, ActionHandlerContext, ActionParamIssue, ActionSession … +4 more (10 total) none dropped
ui/action.zod.ts ACTION_LOCATIONS, Action, ActionAi, ActionAiParsed, ActionAiSchema, ActionLocation … +12 more (18 total) none dropped
ui/app.zod.ts ActionNavItem, ActionNavItemParsed, ActionNavItemSchema, App, AppBranding, AppBrandingSchema … +35 more (41 total) App kept
ui/bulk-action.zod.ts BulkActionDef, BulkActionDefParsed, BulkActionDefSchema, BulkActionExecution, BulkActionExecutionSchema, BulkActionOperation … +3 more (9 total) none dropped
ui/chart.zod.ts ChartAggregate, ChartAggregateFunction, ChartAggregateFunctionSchema, ChartAggregateSchema, ChartAnnotation, ChartAnnotationParsed … +19 more (25 total) none dropped
ui/dashboard.zod.ts DATE_RANGE_DEFAULT_RANGES, DATE_RANGE_PRESETS, Dashboard, DashboardHeader, DashboardHeaderAction, DashboardHeaderActionSchema … +20 more (26 total) none dropped
ui/dataset.zod.ts Dataset, DatasetDimension, DatasetDimensionSchema, DatasetMeasure, DatasetMeasureSchema, DatasetSchema … +3 more (9 total) none dropped
ui/i18n.zod.ts AriaProps, AriaPropsSchema, I18nLabel, I18nLabelSchema, InlineLocaleMap, InlineLocaleMapSchema (6 total) none dropped
ui/page.zod.ts ElementDataSource, ElementDataSourceSchema, InterfacePageConfig, InterfacePageConfigParsed, InterfacePageConfigSchema, PAGE_TYPE_ROADMAP … +17 more (23 total) none dropped
ui/report.zod.ts JoinedReportBlock, JoinedReportBlockSchema, Report, ReportChart, ReportChartParsed, ReportChartSchema … +8 more (14 total) none dropped
ui/responsive.zod.ts ResponsiveStyles, ResponsiveStylesSchema, StyleMap, StyleMapSchema (4 total) none dropped
ui/sharing.zod.ts SharingConfig, SharingConfigParsed, SharingConfigSchema (3 total) none dropped
ui/view.zod.ts AddRecordConfig, AddRecordConfigParsed, AddRecordConfigSchema, AppearanceConfig, AppearanceConfigParsed, AppearanceConfigSchema … +138 more (144 total) none dropped

What the constraint costs and saves — measured

skills/objectstack-platform/references/_index.md, by the skills token ratchet's
own counting convention (ceil(utf8 bytes / 4)):

tree core + deps lines tokens
origin/main (before this PR) 9 core + 27 deps 62 1,387
this PR before ruling D 10 core + 73 deps 109 2,929
this PR now 10 core + 5 deps 41 756

So the patch round is −68 lines / −2,173 tokens against the head the fork
reported, and the index now sits −21 lines / −631 tokens below origin/main
the ruled stack.zod.ts pointer ships, and the catalogue gets smaller than it was
before the PR. skills/objectstack-api/references/_index.md is untouched by this
round (919 tokens, the batch-#36 value). Whole shipped bundle total: 150,816
tokens.

The ratchet does not object, and says why in its own words — _index.md is
generator-owned, so it is measured, not ratcheted:

✓ check-skills-token-ratchet: skills/objectstack-platform/references/_index.md is 756 tokens — generator-owned (`pnpm --filter @objectstack/spec gen:skill-refs`), measured but not ratcheted.
✓ check-skills-token-ratchet: 36 authored bundle file(s) within their ceilings; 10 generator-owned file(s) measured, not ratcheted.

Exactly the ruled files, and nothing else

Regenerating on the merged tree rewrote one _index.md — the platform one.
The stop condition in the ruling (any other index moving) did not trigger. The
regeneration that preceded the allowlist, run on the merged tree with the ruled
1A/2A content already in place, produced no change at all, so the index diff
below is exactly the allowlist's effect.

Premise re-takes, on this branch's origin/main base

Both premises carried into batch #36 were re-measured before the edit, and both hold.

1 — objectstack-api does not teach the pointer. grep -rn "rest-server\|RestServerConfig\|RestApiConfig\|rest server" skills/objectstack-api/ returns exactly one line, and it is the generated index row this PR removes:

skills/objectstack-api/references/_index.md:17:- `node_modules/@objectstack/spec/src/api/rest-server.zod.ts` — REST API Server Protocol

Over the skill's authored markdown alone (the same grep with --exclude=_index.md, and the skill directory holds only SKILL.md and that index) the count is 0. The wider name sweep — CrudEndpointsConfig, MetadataEndpointsConfig, BatchEndpointsConfig, RouteGenerationConfig — is also 0. The premise holds; the earlier reading's "0 hits" was over authored content, and the one hit here is the artifact being corrected.

2 — objectstack-platform teaches the schema, and nothing advertised it. grep -c "ObjectStackDefinition\|defineStack" skills/objectstack-platform/SKILL.md returns 27. grep -rn "stack.zod" skills/*/references/_index.md packages/spec/scripts/build-skill-references.ts returned no match (exit 1) — the file was in no package's core list and in no index's closure. Both hold.

stack.zod.ts carries no module doc block, so the generator takes its designed fallback and emits the export list rather than refusing: the row reads Exports: DatasourceMappingRuleSchema, ArtifactPackageEntrySchema, AssembledPackageBodySchema, ArtifactPackageSchema, ObjectStackDefinitionSchema. No module header was written into the schema source — that is spec-lane content, out of scope here.

Verification

All of it on the final head 3e9e1eae0, working tree clean. Every exit code was
captured by redirect before any pipe, and each gate is quoted from the verdict
line it prints itself.

The gates the ruling names.

✓ pnpm --filter @objectstack/spec run check:skill-refs   (exit 0)
    ✅ 9 generated files in sync with packages/spec
    objectstack-platform: 10 core + 5 deps
✓ pnpm --filter @objectstack/spec run check:skill-docs   (exit 0)
    ✅ Skill docs in sync
✓ node scripts/check-skills-token-ratchet.mjs            (exit 0)
    ✓ skills/objectstack-platform/references/_index.md is 756 tokens — generator-owned, measured but not ratcheted.
    ✓ 36 authored bundle file(s) within their ceilings; 10 generator-owned file(s) measured, not ratcheted.
✓ node scripts/check-skills-token-ratchet.mjs --self-test (exit 0)

checkTransitiveAllowlist — its verdict, and a probe that it is really the
guard speaking.
The guard has no success line to quote: it contributes to the
generator's problems list, and a non-empty list refuses the run in both
modes. A clean gen:skill-refs / check:skill-refs is therefore its verdict, and
on its own that is an argument from silence. So the guard was ablated against the
row this PR adds, with the implementation committed first:

  • mutation leg — one extra member added to the new entry, a path the closure
    never reaches. Confirmed on disk before running anything (injected-marker count
    1, not the editor's exit code). Generator exit 1:
    objectstack-platform → shared/does-not-reach-this.zod.ts is in TRANSITIVE_ALLOWLIST but nothing in the package's core closure imports it — this row keeps a pointer that does not exist.
  • restore leggit checkout HEAD -- on the absolute path, then proved: restored
    blob hash 77a5524028a5d7242253c6052b643af076421ea0 equals the HEAD blob,
    git diff HEAD empty, marker count back to 0. The script carried a
    trap … EXIT INT TERM on an absolute path throughout.
  • restored leg — the same command, exit 0, ✅ 9 generated files in sync.

No rebuild is involved on either leg: the generator and its guards run from
source through tsx, so there is no dist/ for a stale artifact to hide in.

The generator's own test suite — owed because this diff edits tooling
scripts, over and above any derived family. Run through
scripts/pm/os-verify-lock.sh:

Test Files  4 passed (4)
     Tests  137 passed (137)
os-verify-lock: VERDICT command-exit 0 · held the lock 3s · waited 166s

(skill-map-guards.test.ts, file-description.test.ts, protocol-map.test.ts,
query-pointer-row.test.ts — every test file in the repo naming either script.)

The derived family. node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
reads the merge base itself rather than a hand-built diff: 4 paths vs merge
base a55efc6c1, 56 commands. All 56 ran.

  • 55 exit 0.
  • 1 not measured: pnpm check:dual-build-cjs-loads exit 3 — it reads built
    output for the whole workspace and no package is built in this worktree. It says
    so itself: Run pnpm build first. ⛔ This is NOT a pass: nothing was measured.
    Recorded as not measured, not as a pass. This diff ships no package source.

Named verdicts from that run:

✓ check:doc-authoring        — 46 published skill files clean, no internal issue-id references
✓ check:published-files      — 69 publishable package(s) declare a files whitelist
✓ check:nul-bytes            — 7583 text file(s), no raw ASCII control bytes
✓ check:skill-frame-sync     — 2 copies of the decision frame structurally isomorphic
✓ check:skill-compatibility  — 11 SKILL.md reconciled against 79 workspace packages
✓ check:skill-identifier-liveness — 465 citation(s) over 46 published file(s)
✓ check:pm-dispatch-gates    — self-test, 1445 cases pass
✓ check:pm-governed-merges   — self-test; live: the real generator declared 9 output(s)

pnpm lint — the whole repo, not a narrowed scan, through the same lock
wrapper: eslint . --no-inline-config, exit 0, no findings printed.

os-verify-lock: VERDICT command-exit 0 · held the lock 99s (1m39s) · waited 0s

node scripts/pm/check-governed-merges.mjs --test on the four paths returns
GOVERNED, exit 3, and still reports that the generated-surface exception does
not lift either index, because this PR co-edits the generator that exception
would trust:

⛔  GOVERNED — a human merge is the review record for this PR (#9495 regime).
    skills/** ×2 — the published skills catalog
⛔  generated-surface exception (#11705) did NOT lift skills/objectstack-platform/references/_index.md:
    the tree under test modifies the generator this exception trusts

No changeset: this ships no package source. The generator and its guard library are
build scripts and the two indexes are skill markdown, so skip-changeset is the
correct label, and it is on the PR.

This PR stays a draft: governed surface, human merge, two approvers.


Generated by Claude Code

…ir bodies teach

`SKILL_MAP['objectstack-api']` advertised `api/rest-server.zod.ts`, which the
skill's authored markdown never teaches: nothing there names the file,
`RestServerConfig` or any of its sub-configs, or the words "rest server", while
every other core entry is reachable from the body by at least one exported name.
An index entry is a POINTER, so that row sent an agent into `node_modules` for a
lesson that does not exist. The schema keeps existing and stays importable.

The other direction, same rule: `SKILL_MAP['objectstack-platform']` had no
pointer to `stack.zod.ts`, the file declaring the body's main subject — it
teaches `defineStack()` and names `ObjectStackDefinitionSchema`,
`ObjectStackDefinition`, `ObjectStackDefinitionInput` and `ObjectStack` in its
own prose.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@github-actions github-actions Bot added the size/s label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json a55efc6c1b1d8220e523c690d92652d0dd3e3c13packageMentionDocs.

… teaches

`objectstack-platform` declared no `TRANSITIVE_ALLOWLIST`, so its index
published the whole import closure of its core entries — 73 transitive pointers
once `stack.zod.ts` joined the map. Most of them are shapes the SKILL.md never
teaches, and two are shapes the platform retired from its surface, so the
catalogue routed an authoring agent at lessons the body cannot give.

Declare the list, populated by one mechanical rule and nothing else: a closure
member stays only if `skills/objectstack-platform/SKILL.md` names one of that
module's exported names, as an exact word-bounded identifier. Five of the 73
survive. The retired shapes fall out by the rule, not by hand.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox

os-steve commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

ACCEPT (patch round, ruling D) — governed in-seat review of PR #15424, head 3e9e1eae0 (skills seat, 2026-09-05T03:2xZ). Supersedes the hold recorded at the fork (5542681229); ruling D is batch #39, recorded 5548483226.

Implemented-by: claude/issue-15361-skill-map-api-platform-pointers (os-dev subagent, takeover patch round on the delivered branch — a merge of main, no rewrite)
Reviewed-by: session_019RfFHiRCSs3JXLK4cwcfox (skills seat)

Verified in a detached compare worktree at the PR head against merge-base a55efc6c1, not from the report: four files. TRANSITIVE_ALLOWLIST['objectstack-platform'] lives where the map is declared — packages/spec/scripts/lib/skill-map-guards.ts, beside the guard that constrains it, not in the generator file the ruling named (a location reading, not a change of substance; the generator imports it). Five closure members survive the ruled grep rule — data/field.zod.ts, data/hook.zod.ts, data/object.zod.ts, security/rls.zod.ts, ui/app.zod.ts — and both shapes the fork named (automation/state-machine.zod.ts, data/date-macros.zod.ts) fell out by the rule, not by hand. The platform index is 41 lines / 756 tokens (109 / 2929 at the forked head; 62 / 1387 on main); the api index keeps its one-row drop; batch #36's 1A · 2A stand. The rule applied to the whole closure as ruled also drops 22 transitive pointers that were on main before this PR — the census table in the body names each. Gates from the dev's run on this head: check:skill-refs "9 generated files in sync" (platform 10 core + 5 deps), check:skill-docs in sync, the token ratchet measured-not-ratcheted for the index, whole-repo lint through the lock, the generator's own four suites 137 tests, the allowlist guard ablated on a committed head (a non-closure row refuses the run, restore proved by blob hash), 55 of 56 derived commands exit 0 with the one exit 3 recorded as NOT MEASURED (a whole-workspace build prerequisite). Governed probe: exit 3, skills/** ×2, the generated-surface exception correctly not lifted because the generator itself changes. CI on 3e9e1eae0: 40 check runs, 36 success, 4 skipped, none failing. No model names, no card numbers added to the code.

One standing consequence, recorded not reopened: four of the five kept rows are kept by a name the platform SKILL.md uses as ordinary prose (App, Hook, Lifecycle, RLS); the ruling forbids judgement rows, so they stay — and a future prose edit of that skill can re-admit a module to the published index by the same rule. The index is generator-owned and measured, so such a change is visible at the next regeneration.

Landing regime: governed (skills/** + the spec generator) ⇒ the PR stays a draft; reviewers os-zhuang + hotlong requested in this same act; human merge, ⛔ no auto-merge. Closes #15361 and #15264.


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 5, 2026 03:28
@os-zhuang
os-zhuang enabled auto-merge September 5, 2026 03:28
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 5, 2026
Merged via the queue into main with commit 1c14214 Sep 5, 2026
42 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-15361-skill-map-api-platform-pointers branch September 5, 2026 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tooling

Projects

None yet

3 participants